﻿#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Neat;
using Neat.Mathematics;
using Neat.GUI;
using Neat.Graphics;
using Sectors;
using Microsoft.Xna.Framework.Input;
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
using SectorsDesigner.MapMaker;
#endregion

namespace SectorsDesigner
{
    public partial class SectorsMapMakerControl : GraphicsDeviceControl
    {
        public string FileName = "";

        public void Open(string filename)
        {
            if (!File.Exists(filename))
            {
                //File does not exist
                return;
            }

            New();
            int i = 0;
            string[] data;
            try
            {
                data = File.ReadAllLines(filename);
            }
            catch
            {
                MessageBox.Show("Couldn't open file.");
                return;
            }

            ReadVertices(data[0]);
            ReadDeleted(data[1]);
            
            if (data[2] != ":edges")
                throw new Exception("File is corrupt");
            i=3;
            while (data[i] != ":sectors")
                Edges.Add(String2Edge(data[i++]));
            i++;
            while (i < data.Length)
                AddSector(String2Sector(data[i++]));
            
            RefreshListBox();
        }

        public void Save(string filename)
        {
            StreamWriter sw = new StreamWriter(filename);
            sw.WriteLine(WriteVertices());
            sw.WriteLine(WriteDeleted());
            sw.WriteLine(":edges");
            foreach (var item in Edges)
            {
                sw.WriteLine(Edge2String(item));
            }
            sw.WriteLine(":sectors");
            foreach (var item in Sectors)
            {
                sw.WriteLine(Sector2String(item));
            }
            sw.Close();
        }

        public void CreateWorld()
        {
            World = new World();
            World.Walls = new List<Wall>();
            int i = 0;
            foreach (var item in Edges)
            {
                if (DeletedEdges.Contains(i++)) continue;
                World.Walls.AddRange(item.ToWalls());
            }

            foreach (var item in Sectors)
            {
                Sector s = item.ToSector(World);
                s.Vertices = item.Mesh.ToVertexList();
                s.Mesh.AutoTriangulate = true;
                s.Mesh.Triangulate();
                //s.Name = "sector" + World.Sectors.Count.ToString();
                World.Sectors.Add(s);
            }
            //World.FindWalls();
        }

        public void ReadVertices(string item)
        {
            var vs = item.Trim().Split(' ');
            Vertices = new List<Vector2>();
            foreach (var v in vs)
            {
                Vertices.Add(GeometryHelper.String2Vector(v));
            }
        }

        public string WriteVertices()
        {
            string s = "";
            foreach (var v in Vertices)
            {
                s += GeometryHelper.Vector2String(v) + " ";
            }
            return s.Trim();
        }

        public string WriteDeleted()
        {
            string s = "";
            foreach (var i in DeletedVertices)
            {
                s += i.ToString() + " ";
            }
            s = s.Trim() + "|";
            foreach (var i in DeletedEdges)
            {
                s += i.ToString() + " ";
            }
            return s.Trim();
        }

        public void ReadDeleted(string s)
        {
            var ds = s.Trim().Split('|');
            DeletedVertices = new List<int>();
            DeletedEdges = new List<int>();
            try
            {
                foreach (var i in ds[0].Trim().Split(' '))
                {
                    if (!string.IsNullOrEmpty(i))  DeletedVertices.Add(int.Parse(i));
                }
            }
            catch { }
            try
            {
                foreach (var i in ds[1].Trim().Split(' '))
                {
                    if (!string.IsNullOrEmpty(i)) DeletedEdges.Add(int.Parse(i));
                }
            }
            catch { }
        }

        public void ReadEdges(string item)
        {
            //TODO: WALL INFO
            var eg = item.Trim().Split(' ');
            Edges = new List<Edge>();
            foreach (var e in eg)
            {
                Edges.Add(String2Edge(e));
            }
        }

        public string Edge2String(Edge e)
        {
            string s =
                e.Wall.Name + " " + //0
                GeometryHelper.Vector2String(e.Wall.StartPos) + " " + //1
                GeometryHelper.Vector2String(e.Wall.EndPos) + " " + //2
                e.Wall.Texture + " " + //3
                e.Wall.TextureB + " " + //4
                e.Wall.TextureU + " " + //5
                e.Wall.TextureL + " " + //6
                GeometryHelper.Vector2String(e.Wall.TextureUV) + " " + //7
                GeometryHelper.Vector2String(e.Wall.TextureBUV) + " " + //8
                GeometryHelper.Vector2String(e.Wall.TextureUUV) + " " + //9
                GeometryHelper.Vector2String(e.Wall.TextureLUV) + " " + //10
                ((int)e.Wall.WallType).ToString() + " "; //11

            foreach (var i in e.Indices)
            {
                s += i.ToString() + " "; //12
            }
            return s.Trim();
        }

        public Edge String2Edge(string s)
        {
            string[] elements = s.Trim().Split(' ');
            List<int> l = new List<int>();
            for (int i = 12; i < elements.Length; i++) l.Add(int.Parse(elements[i]));
            Wall w = new Wall();
            w.Name = elements[0];
            w.StartPos = GeometryHelper.String2Vector(elements[1]);
            w.EndPos = GeometryHelper.String2Vector(elements[2]);
            w.Texture = elements[3];
            w.TextureB = elements[4];
            w.TextureU = elements[5];
            w.TextureL = elements[6];
            w.TextureUV = GeometryHelper.String2Vector(elements[7]);
            w.TextureBUV = GeometryHelper.String2Vector(elements[8]);
            w.TextureUUV = GeometryHelper.String2Vector(elements[9]);
            w.TextureLUV = GeometryHelper.String2Vector(elements[10]);
            w.WallType = (Sectors.Wall.WallTypes)(int.Parse(elements[11]));
            Edge e = new Edge(Vertices, w);
            foreach (var item in l)
            {
                e.Indices.Add(item);
            }
            return e;
        }

        public string Sector2String(SectorInfo item)
        {
            string s =
                item.FloorHeight.ToString() + " " + //0
                item.CeilingHeight.ToString() + " " + //1
                item.FloorTexture + " " + //2
                item.CeilingTexture + " " + //3
                GeometryHelper.Vector2String(item.FloorUV) + " " + //4
                GeometryHelper.Vector2String(item.CeilingUV) + " " + //5
                item.UpperSector + " " + //6
                item.LowerSector + " " + //7
                item.DamagePoints.ToString() + " " + //8
                item.IdleTime.ToString() + " " + //9
                item.LightIntensity.ToString() + " " + //10
                ((int)item.SectorType).ToString() + " " + //11
                item.Name + " "; //12
            foreach (var edge in item.Mesh.Indices)
            {
                s += edge.ToString() + " ";
                //s += GeometryHelper.Vector2String(vertex) + " "; //13, ...
            }
            return s.Trim();
        }

        public SectorInfo String2Sector(string item)
        {
            string[] elements = item.Trim().Split(' ');
            List<int> l = new List<int>();
            for (int i = 13; i < elements.Length; i++) l.Add(int.Parse(elements[i]));
                //l.Add(GeometryHelper.String2Vector(elements[i]));
            return new SectorInfo(
                float.Parse(elements[0]),
                float.Parse(elements[1]),
                elements[2],
                elements[3],
                GeometryHelper.String2Vector(elements[4]),
                GeometryHelper.String2Vector(elements[5]),
                elements[6],
                elements[7],
                float.Parse(elements[8]),
                int.Parse(elements[9]),
                float.Parse(elements[10]),
                (Sector.SectorTypes)(int.Parse(elements[11])),
                elements[12],
                l,Edges);
        }
    }
}